/*+***********************************************************************************
 Filename: 9k_mcu01_mycore_v003\src\top.v
 Description: a simple MCU with rom, ram. without interruption.

 Modification:
   2025.08.16 Creation   H.Zheng
              porting from previous design.

Copyright (C) 2024-2025  Zheng Hui (hzheng@gzhu.edu.cn)

License: MulanPSL-2.0

***********************************************************************************-*/

module top (
  input wire [1:0] button,
  input wire sys_clk,
  output wire [5:0] led
);

  //reset signals
  wire reset_n = button[1];


  //core
  wire [31:0] ibus_addr;
  wire [31:0] instruction;
  wire [31:0] monitor_port;
  wire [31:0] core_loadstore_addr;
  wire [31:0] core_loadstore_data_in;
  wire [31:0] core_loadstore_data_out;
  wire core_loadstore_ce;
  wire core_loadstore_we;
  wire [3:0] core_loadstore_wmask;

  zh_core_v01 m_core(
    .clk(sys_clk),
    .rst_n(reset_n),

    .ibus_addr(ibus_addr),
    .instruction_i(instruction),

    .core_loadstore_addr(core_loadstore_addr),
    .core_loadstore_data_in(core_loadstore_data_in),
    .core_loadstore_data_out(core_loadstore_data_out),
    .core_loadstore_ce(core_loadstore_ce),
    .core_loadstore_we(core_loadstore_we),
    .core_loadstore_wmask(core_loadstore_wmask),

    .monitor_port(monitor_port)
 );

  //load/store bus multiplexer
  wire mux_d0_en = core_loadstore_ce & (core_loadstore_addr[31:28] == 4'b0000);
  wire mux_d1_en = core_loadstore_ce & (core_loadstore_addr[31:28] == 4'b0001);
  wire mux_d2_en = core_loadstore_ce & (core_loadstore_addr[31:28] == 4'b0010);

  wire[31:0] mux_d0_data_i, mux_d1_data_i, mux_d2_data_i;
  wire[31:0] mux_d0_addr_o, mux_d1_addr_o, mux_d2_addr_o;
  wire[31:0] mux_d1_data_o, mux_d2_data_o;

  assign core_loadstore_data_in = mux_d0_en ? mux_d0_data_i :
                     mux_d1_en ? mux_d1_data_i :
                     mux_d2_en ? mux_d2_data_i : 32'b0;
  assign mux_d0_addr_o = (mux_d0_en) ? core_loadstore_addr : 32'b0;
  assign mux_d1_addr_o = (mux_d1_en) ? core_loadstore_addr : 32'b0;
  assign mux_d2_addr_o = (mux_d2_en) ? core_loadstore_addr : 32'b0;
  assign mux_d1_data_o = (mux_d1_en) ? core_loadstore_data_out : 32'b0;
  assign mux_d2_data_o = (mux_d2_en) ? core_loadstore_data_out : 32'b0;

  //rom
  zh_dprom_async_v01 I_ROM(
    .addr_a(ibus_addr[14:2]), 
    .dout_a(instruction),
    .addr_b(mux_d0_addr_o[14:2]), 
    .dout_b(mux_d0_data_i)
  );

  //sram
  zh_sram_async_v01 D_RAM(
    .addr(mux_d2_addr_o[14:2]), 
    .dout(mux_d2_data_i),
    .wclk(sys_clk), 
    .wen(mux_d2_en & core_loadstore_we),
    .wmask(core_loadstore_wmask),
    .din(mux_d2_data_o)
  );

  //output
  assign led = ~monitor_port[29:24];
//  assign led = ~monitor_port[5:0];

endmodule